home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / HardwareProjects / VideoText.lha / VideoText4.2 / source / cct.p < prev    next >
Encoding:
Text File  |  1995-06-22  |  9.2 KB  |  259 lines

  1. UNIT cct; {$project vt }
  2. { Programmierung des CCT-Chips (Computer Controlled Teletext) SAA5246 }
  3.  
  4. INTERFACE; FROM vt USES global,i2c_serial;
  5.  
  6. VAR aktspeicher: Integer;   { der Speicher, in dem die VT-Uhr läuft }
  7.  
  8. PROCEDURE display_select(speicher: Byte);
  9. PROCEDURE TV_display(mode: Byte);
  10. FUNCTION VTstat: Byte;
  11. PROCEDURE sperren(speicher: Byte);
  12. PROCEDURE anfordern(speicher: Byte; page, subpage: Integer; mask: Byte);
  13. PROCEDURE init_CCT;
  14. FUNCTION seite_da(speicher: Byte): Boolean;
  15. PROCEDURE gettime(speicher: Byte; VAR zeit: Str80);
  16. PROCEDURE gethead(speicher: Byte; VAR head: Str80);
  17. PROCEDURE getpage(speicher: Byte; seite: p_onepage; ganz: Boolean);
  18.  
  19. { ---------------------------------------------------------------------- }
  20.  
  21. IMPLEMENTATION;
  22.  
  23. {$opt q,s+,i+ } { keine Laufzeitprüfungen außer Stack und Feldindizes }
  24.  
  25. CONST SAA5246 = $22;
  26.       PBLF = $20;
  27.       DOCARE =  $10;
  28.       NOTHOLD = $08;
  29.       SERMAG = $0800; { C11 }
  30.  
  31. VAR i2cdata: ARRAY[1..20] OF Byte;    { kleiner Puffer für Kommandos }
  32.  
  33. PROCEDURE display_select{(speicher: Byte)};
  34. { Einen der 8 Seitenspeicher zur Anzeige auswählen }
  35. BEGIN
  36.   setregister(SAA5246,4,speicher);
  37. END;
  38.  
  39. PROCEDURE TV_display{(mode: Byte)};
  40. { Art der Anzeige am Fernseher auswählen. }
  41. BEGIN
  42.   i2cdata[1] := 5;
  43.   CASE mode OF
  44.     2: { Normalseiten bildfüllend, Schlagzeilen als Boxen }
  45.       BEGIN  i2cdata[2] := %11001100; i2cdata[3] := %01001111; END;
  46.     1: { Normalseiten als Boxen, Schlagzeilen transparent }
  47.       BEGIN  i2cdata[2] := %11001111; i2cdata[3] := %00001111; END;
  48.     OTHERWISE  { Anzeige aus }
  49.       BEGIN  i2cdata[2] := %00000011; i2cdata[3] := %00000011; END;
  50.   END;
  51.   i2cdata[4] := %00000111;
  52.   i2cbusIO(SAA5246,^i2cdata,4);
  53. END;
  54.  
  55. FUNCTION VTstat{: Byte};
  56. { Liest aus dem CCT das Register R11B. Bedeutung: bit0 - Videosignal vorh., }
  57. { bit1 - Textsignal vorh., bit2-5 - ROM-Version }
  58. BEGIN
  59.   setregister(SAA5246,0,%00000001);   { R11B aktivieren }
  60.   VTstat := getregister(SAA5246,11);    { Status lesen }
  61.   setregister(SAA5246,0,%00000000);   { R11 aktivieren }
  62. END;
  63.  
  64. PROCEDURE sperren{(speicher: Byte)};
  65. { Seitensuche eines Empfangskreises anhalten, damit nicht evtl. niederpriore }
  66. { Empfangskreise behindert werden. Die Sperre wird bei Programmierung einer }
  67. { neuen Seitenanforderung automatisch aufgehoben. }
  68. BEGIN
  69.   i2cdata[1] := 2;
  70.   i2cdata[2] := speicher*16;
  71.   i2cdata[3] := 0;
  72.   i2cbusIO(SAA5246,^i2cdata,3);
  73. END;
  74.  
  75. PROCEDURE anfordern{(speicher: Byte; page, subpage: Integer; mask: Byte)};
  76. { Einlesen einer Seite in einen Seitenspeicher 0..7 anfordern, Unterseite nur }
  77. { direkt anfordern, wenn subpage > 0 }
  78. { <mask> ist eine dreistellige Binärzahl, wo eine '0' steht, wird in der }
  79. { entsprechenden Ziffer der angeforderten Seitennummer das DOCARE-Bit }
  80. { gelöscht. }
  81. VAR lauf: Integer;
  82. BEGIN
  83.   { Seitenanforderung beschreiben: }
  84.   i2cdata[1] := 2;
  85.   i2cdata[2] := speicher*16;
  86.   i2cdata[3] := ((page SHR 8) AND $7) OR NOTHOLD;
  87.   i2cdata[4] := (page SHR 4) AND $F;
  88.   i2cdata[5] := page AND $F;
  89.   IF page > 0 THEN
  90.     FOR lauf := 3 TO 5 DO
  91.       IF Odd(mask SHR (5-lauf)) THEN
  92.         i2cdata[lauf] := i2cdata[lauf] OR DOCARE;
  93.   i2cdata[6] := (subpage SHR 12) AND $3;
  94.   i2cdata[7] := (subpage SHR 8) AND $F;
  95.   i2cdata[8] := (subpage SHR 4) AND $7
  96.   i2cdata[9] := subpage AND $F;
  97.   IF subpage > 0 THEN
  98.     FOR lauf := 6 TO 9 DO  i2cdata[lauf] := i2cdata[lauf] OR DOCARE;
  99.   i2cbusIO(SAA5246,^i2cdata,9)
  100. END;
  101.  
  102. PROCEDURE init_CCT;
  103. VAR i: Byte;
  104. BEGIN
  105.   { Wichtig in R1: bit5 - ACQ OFF, Decoder-NotAus; bit2 - TCS ON, }
  106.   { RGB-Ausgangssignal wird mit Fernsehbild synchronisiert. }
  107.   setregister(SAA5246,1,%00000100);
  108.   { Seitensuche sperren: }
  109.   FOR i := 0 TO maxactive-1 DO BEGIN
  110.     sperren(i); activejobs[i].pg := 0;
  111.   END;
  112.   { alle Seitenspeicher löschen: }
  113.   FOR i := 0 TO 7 DO BEGIN
  114.     setregister(SAA5246,8,%00001000 OR i); Delay(2);
  115.     { Löschvorgang dauert bis zu 22 ms, darum mal jeweils 40 ms warten. }
  116.   END;
  117.   { R11 aktivieren }
  118.   setregister(SAA5246,0,%00000000);
  119.   { Fernsehdarstellung einschalten }
  120.   display_select(0);
  121.   TV_display(2);
  122. END;
  123.  
  124. FUNCTION seite_da{(speicher: Byte): Boolean};
  125. { Überprüft, ob die für einen Speicher 0..7 angeforderte Seite bereits }
  126. { eingetroffen ist. Das Statusflag PBLF, das in diesem Fall gelöscht ist, }
  127. { muß danach wieder gesetzt werden. Das geschieht entweder implizit beim }
  128. { Programmieren einer neuen Seitenanforderung oder explizit durch }
  129. { Schreibzugriff, in diesem Programm in getpage(). }
  130. { Problem: das Statusflag PBLF bezieht sich auf den Empfang der Kopfzeile, }
  131. { nicht etwa den Empfang der kompletten Seite. Genauer gesagt: für letzteres }
  132. { existiert überhaupt kein Statusflag! }
  133. { Nun ist das nicht ganz so tragisch, nach Empfang der Kopfzeile kann man }
  134. { bereits bedenkenlos die Statuszeile 25 mit Steuerbits und Seitennummer }
  135. { lesen. Und in vielen Fällen geht es sogar gut, sofort mit dem Einlesen }
  136. { der gesamten Seite zu beginnen, da sich nämlich maximal 11 Seiten pro }
  137. { Sekunde über den I²C-Bus schaufeln lassen, während der Videotext selbst }
  138. { mit ca. 13 Seiten pro Sekunde einrollt: Die noch leere Seite wird }
  139. { schneller aufgefüllt, als sie ausgelesen werden kann. }
  140. { Probleme entstehen natürlich, wenn der Empfang der VT-Seite länger als }
  141. { ca. 1/10 s dauert. Das ist möglich, wenn der Sender nicht alle zur }
  142. { VT-Übertragung zulässigen Rasterzeilen ausnutzt, oder wenn er gar den }
  143. { Magazin-gemischten Übertragungsmodus verwendet. Letzteres ist aber an }
  144. { einem Statusflag (C11) vom Programm aus erkennbar, hm ... }
  145. BEGIN
  146.   seite_da := False;
  147.   { Byte 9 der Statuszeile (Zeile 25) adressieren ... }
  148.   i2cdata[1] := 8;
  149.   i2cdata[2] := speicher;
  150.   i2cdata[3] := 25; i2cdata[4] := 9;
  151.   i2cbusIO(SAA5246,^i2cdata,4);
  152.   IF i2c_status<>0 THEN Exit;
  153.   { ... und auslesen: }
  154.   i2cbusIO(SAA5246,^i2cdata,-1);
  155.   IF i2c_status<>0 THEN Exit;
  156.   seite_da := (i2cdata[1] AND PBLF)=0;
  157. END;
  158.  
  159. PROCEDURE gettime{(speicher: Byte; VAR zeit: Str80)};
  160. { liest aus einer Speicherseite 0..7 des CCT-Bausteins die Uhrzeit }
  161. VAR i: Integer;
  162. BEGIN
  163.   zeit := '        ';
  164.   { Uhrzeit aus der Seite im CCT lesen: Zeile 0, Spalte 32 }
  165.   i2cdata[1] := 8;
  166.   i2cdata[2] := speicher;
  167.   i2cdata[3] := 0; i2cdata[4] := 32;
  168.   i2cbusIO(SAA5246,^i2cdata,4);
  169.   IF i2c_status<>0 THEN Exit;
  170.   { Uhrzeit lesen: }
  171.   i2cbusIO(SAA5246,^i2cdata,-8);
  172.   IF i2c_status<>0 THEN Exit;
  173.   FOR i := 1 TO 8 DO
  174.     IF i2cdata[i] IN [32..127] THEN zeit[i] := Chr(i2cdata[i]);
  175. END;
  176.  
  177. PROCEDURE gethead{(speicher: Byte; VAR head: Str80)};
  178. { liest die 24 Byte Titelzeile zwischen Statusfeld und Uhrzeit }
  179. VAR i: Integer;
  180. BEGIN
  181.   head := '';
  182.   { Seitenspeicher addressieren: Zeile 0, Spalte 8 }
  183.   i2cdata[1] := 8;
  184.   i2cdata[2] := speicher;
  185.   i2cdata[3] := 0; i2cdata[4] := 8;
  186.   i2cbusIO(SAA5246,^i2cdata,4);
  187.   IF i2c_status<>0 THEN Exit;
  188.   { Zeile lesen: }
  189.   i2cbusIO(SAA5246,^head,-24);
  190.   IF i2c_status<>0 THEN Exit;
  191.   FOR i := 1 TO 24 DO
  192.     IF NOT (Ord(head[i]) IN [32..127]) THEN head[i] := ' ';
  193.   head[25] := #0;
  194. END;
  195.  
  196. PROCEDURE getpage{(speicher: Byte; seite: p_onepage; ganz: Boolean)};
  197. { Liest eine Speicherseite (0..7) aus dem CCT-Baustein aus und speichert }
  198. { diese Seite im Amiga. Für <ganz>=false werden nur die Statusinformationen }
  199. { aus Zeile 25 gelesen. }
  200. { Abschließend wird das Statusflag PBLF wieder gesetzt! }
  201. VAR i,h: Integer;
  202.     status: ARRAY [0..9] OF Byte;
  203.     hex: ARRAY [0..16] OF Char;
  204.     s: str80;
  205. BEGIN
  206.   hex := '0123456789ABCDEF';
  207.   seite^.pg := 0; seite^.sp := 0; seite^.cbits := 0;
  208.   { Status aus der Seite im CCT lesen: Zeile 25, Spalte 0 }
  209.   i2cdata[1] := 8;
  210.   i2cdata[2] := speicher;
  211.   i2cdata[3] := 25; i2cdata[4] := 0;
  212.   i2cbusIO(SAA5246,^i2cdata,4);
  213.   IF i2c_status<>0 THEN Exit;
  214.   i2cbusIO(SAA5246,^status,-10);
  215.   IF i2c_status<>0 THEN Exit;
  216.   seite^.pg := (status[0] AND $F) + (status[1] AND $F) SHL 4
  217.                                   + (status[8] AND $7) SHL 8;
  218.   IF seite^.pg<$100 THEN seite^.pg := seite^.pg + $800;
  219.   seite^.sp := (status[2] AND $F)       + (status[3] AND $7) SHL 4
  220.              + (status[4] AND $F) SHL 8 + (status[5] AND $3) SHL 12;
  221.   seite^.cbits := (status[3] AND $08) SHL 1   { C4 }
  222.                 + (status[5] AND $0C) SHL 3   { C5, C6 }
  223.                 + (status[6] AND $0F) SHL 7   { C7, C8, C9, C10 }
  224.                 + (status[7] AND $0F) SHL 11  { C11, C12..C14 }
  225.   IF ganz THEN BEGIN
  226.     { Seite aus CCT lesen. Richtigen Speicher, Zeile 0, Spalte 0 adressieren: }
  227.     i2cdata[1] := 8;
  228.     i2cdata[2] := speicher;
  229.     i2cdata[3] := 0; i2cdata[4] := 0;
  230.     i2cbusIO(SAA5246,^i2cdata,4);
  231.     IF i2c_status<>0 THEN Exit;
  232.     { Seite einlesen: }
  233.     i2cbusIO(SAA5246,^seite^.chars,-960);
  234.     IF i2c_status<>0 THEN Exit;
  235.     { in den freien Anfang der 1. Zeile die Unterseitennummer eintragen }
  236.     seite^.chars[1] := Ord('(');
  237.     seite^.chars[2] := Ord(hex[status[5] AND $3]);
  238.     seite^.chars[3] := Ord(hex[status[4] AND $F]);
  239.     seite^.chars[4] := Ord(hex[status[3] AND $7]);
  240.     seite^.chars[5] := Ord(hex[status[2] AND $F]);
  241.     seite^.chars[6] := Ord(')');
  242.     seite^.chars[7] := Ord(' ');
  243.     IF status[7] AND $01=0 THEN BEGIN  { C11=0: Magazin-gemischte Übertragung, }
  244.       seite^.chars[1] := Ord('<');  { Modus für den Benutzer erkennbar machen }
  245.       seite^.chars[6] := Ord('>');
  246.     END;
  247.     { aus dem zur Anzeige aktivierten Seitenspeicher die Uhrzeit holen: }
  248.     IF speicher<>aktspeicher THEN BEGIN
  249.       gettime(aktspeicher,s);
  250.       FOR i := 1 TO 8 DO
  251.         seite^.chars[31+i] := Ord(s[i]);
  252.     END;
  253.   END;
  254. END;
  255.  
  256. BEGIN  { Initialisierungsteil }
  257.   aktspeicher := 0;
  258. END.
  259.